package com.yuyang.wifi.views.recyclerview.adapter;

import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.yuyang.wifi.views.recyclerview.exception.BaseRecyclerViewException;
import com.yuyang.wifi.views.recyclerview.model.FooterItem;
import com.yuyang.wifi.views.recyclerview.model.HeaderItem;
import com.yuyang.wifi.views.recyclerview.model.SimpleItem;
import com.yuyang.wifi.views.recyclerview.ui.BaseRecyclerView;
import com.yuyang.wifi.views.recyclerview.ui.ViewPreparedUtil;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

/**
 * Created by tik on 17/8/8.
 * 带有空视图和自动补全剩余空间功能的RecyclerViewAdapter
 */

public class RecyclerViewAdapterWrapper<DataType> extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
	protected Context mContext;
	protected LayoutInflater mInflater;
	protected SparseArray<SimpleItem> mHeaderItemTypes;
	protected SparseArray<SimpleItem> mFooterItemTypes;
	protected ArrayList<SimpleItem> mHeaderItems;
	protected ArrayList<SimpleItem> mFooterItems;
	protected RecyclerView.Adapter mOriginalAdapter;
	protected CommonAdapter mCommonAdapter;
	private boolean mTryAutoFixPositionToEnd;

	//RemainArea
	protected int mRemainAreaItemResId;
	protected int mItemHeight;
	protected int mDataAreaOffset;
	protected BaseRecyclerView mRecyclerView;
	protected int mRecyclerViewHeight;
	protected SimpleItem mRemainAreaItem;
	protected int mRemainAreaMinHeight;
	private boolean hasAddRecyclerViewPreparedListener;
	protected int mEmptyViewResId;

	public RecyclerViewAdapterWrapper(Context context, List objects) {
		mOriginalAdapter = createOriginalAdapter(objects,context);
		if (mOriginalAdapter instanceof CommonAdapter){
			mCommonAdapter = (CommonAdapter) mOriginalAdapter;
		}
		initAdapter(context);
	}

	private void initAdapter(Context context) {
		mContext = context;
		mInflater = LayoutInflater.from(mContext);
		mHeaderItems = new ArrayList<>();
		mFooterItems = new ArrayList<>();
		mHeaderItemTypes = new SparseArray<>();
		mFooterItemTypes = new SparseArray<>();
		mOriginalAdapter.registerAdapterDataObserver(new DataObserver());
	}

	public RecyclerViewAdapterWrapper(Context context, RecyclerView.Adapter originalAdapter) {
		mOriginalAdapter = originalAdapter;
		initAdapter(context);
	}


	public RecyclerView.Adapter createOriginalAdapter(List objects, Context context) {
		return createCommonAdapter(objects, context);
	}

	@NonNull
	public CommonAdapter createCommonAdapter(List objects, Context context) {
		return new CommonAdapter<DataType>(context,objects) {
			@Override
			public void convert(CommonViewHolder holder, DataType data) {
				RecyclerViewAdapterWrapper.this.convert(holder,data);
			}

			@Override
			public int getItemLayoutId() {
				int layoutId = super.getItemLayoutId();
				if (layoutId > 0){
					return layoutId;
				}else {
					return RecyclerViewAdapterWrapper.this.getItemLayoutId();
				}
			}
		};
	}


	public RecyclerView.Adapter getOriginalAdapter() {
		return mOriginalAdapter;
	}

	public void setOriginalAdapter(RecyclerView.Adapter originalAdapter) {
		mOriginalAdapter = originalAdapter;
	}

	public boolean isTryAutoFixPositionToEnd() {
		return mTryAutoFixPositionToEnd;
	}


	public int getRemainAreaMinHeight() {
		return mRemainAreaMinHeight;
	}

	public void setRemainAreaMinHeight(int remainAreaMinHeight) {
		mRemainAreaMinHeight = remainAreaMinHeight;
		addRecyclerViewLayoutListener();
	}

	public int getItemLayoutId() {
		return 0;
	}

	public void setItemLayoutId(int itemLayoutId) {
		if (mCommonAdapter != null){
			mCommonAdapter.setItemLayoutId(itemLayoutId);
		}
	}

	public void setTryAutoFixPositionToEnd(boolean tryAutoFixPositionToEnd) {
		mTryAutoFixPositionToEnd = tryAutoFixPositionToEnd;
	}

	public BaseRecyclerView getRecyclerView() {
		return mRecyclerView;
	}

	public void setRecyclerView(BaseRecyclerView recyclerView) {
		mRecyclerView = recyclerView;
	}

	public void addHeaderView(View view){
		addHeaderItem(new HeaderItem(view));
	}

	public void addFooterView(View view){
		addFooterItem(new FooterItem(view));
	}

	public void addHeaderItem(HeaderItem headerItem){
		mHeaderItems.add(headerItem);
		mHeaderItemTypes.put(headerItem.getItemType(),headerItem);
	}

	public void addFooterItem(FooterItem footerItem){
		mFooterItems.add(footerItem);
		mFooterItemTypes.put(footerItem.getItemType(),footerItem);
	}


	protected void doFullDataArea(){
		if (mItemHeight < 0 || mDataAreaOffset < 0 ){
			throw new BaseRecyclerViewException("ItemHeight小于0或DataAreaOffset小于0");
		}
		int height = getRemainItemHeight();
		if (height > 0 ){
			View remainAreaView = createRemainAreaView(height);
			if (remainAreaView != null){
				mRemainAreaItem = new SimpleItem(remainAreaView);
			}else {
				mRemainAreaItem = null;
			}
		}else {
			mRemainAreaItem = null;
		}
	}

	protected View createRemainAreaView(int height){
		int resId = 0;
		if (getDataSize() == 0){
			resId = mEmptyViewResId;
		}
		if(resId <= 0){
			resId = mRemainAreaItemResId;
		}
		if (resId <= 0){
			return null;
		}
		View remainAreaView = mInflater.inflate(resId,mRecyclerView,false);
		RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) remainAreaView.getLayoutParams();
		layoutParams.height = height;
		remainAreaView.setLayoutParams(layoutParams);
		return remainAreaView;
	}

	public int getItemHeight() {
		return mItemHeight;
	}

	public void setItemHeight(int itemHeight) {
		mItemHeight = itemHeight;
	}

	public int getRemainItemHeight(){
		int height = mRecyclerViewHeight - mItemHeight * getDataSize() - mDataAreaOffset;
		if (height < mRemainAreaMinHeight){
			height = mRemainAreaMinHeight;
		}
		return height;
	}

	public int getDataAreaOffset() {
		return mDataAreaOffset;
	}

	public void setDataAreaOffset(int dataAreaOffset) {
		mDataAreaOffset = dataAreaOffset;
	}

	public int getDataSize(){
		return mOriginalAdapter.getItemCount();
	}

	public void fullDataArea(int remainAreaItemResId){
		fullDataArea(remainAreaItemResId,-1,-1);
	}

	public void fullDataArea(int remainAreaItemResId,int itemHeight){
		fullDataArea(remainAreaItemResId,itemHeight,-1);
	}

	public void fullDataArea(int remainAreaItemResId,int itemHeight,int dataAreaOffset){
		fullDataArea(remainAreaItemResId,itemHeight,dataAreaOffset,true);
	}

	public void fullDataArea(int remainAreaItemResId,int itemHeight,int dataAreaOffset,boolean tryAutoFixPositionToEnd){
		checkRecyclerView();
		setTryAutoFixPositionToEnd(tryAutoFixPositionToEnd);
		if (itemHeight >= 0){
			mItemHeight = itemHeight;
		}
		if (dataAreaOffset >= 0){
			mDataAreaOffset = dataAreaOffset;
		}
		mRemainAreaItemResId = remainAreaItemResId;
		addRecyclerViewLayoutListener();
	}

	protected void addRecyclerViewLayoutListener(){
		if (mRecyclerViewHeight <= 0 && !hasAddRecyclerViewPreparedListener){
			hasAddRecyclerViewPreparedListener = true;
			ViewPreparedUtil.addViewPreparedListener(mRecyclerView, new ViewPreparedUtil.OnViewPreparedListener(true) {
				@Override
				public void onFirstPrepared(View view) {
					mRecyclerViewHeight = view.getHeight();
					afterRecyclerViewPrepared();
				}
			});
		}
	}

	protected void afterRecyclerViewPrepared(){
		//处理剩余的数据区域
		if ((wantFullDataArea() || hasSetEmptyView()) && !hasFullDataArea()){
			doFullDataArea();
		}
	}

	public void setEmptyViewResId(int emptyResId,int dataAreaOffset){
		if (dataAreaOffset > 0){
			mDataAreaOffset = dataAreaOffset;
		}
		checkRecyclerView();
		mEmptyViewResId = emptyResId;
		addRecyclerViewLayoutListener();
	}
	public void setEmptyViewResId(int emptyResId){
		setEmptyViewResId(emptyResId,0);
	}

	private void checkRecyclerView(){
		if (mRecyclerView == null){
			throw new BaseRecyclerViewException("尚未在Adapter中设置RecyclerView");
		}
	}

	public boolean wantFullDataArea(){
		return mRemainAreaItemResId > 0;
	}

	public boolean hasFullDataArea(){
		return mRemainAreaItem != null;
	}

	public boolean hasSetEmptyView(){
		return mEmptyViewResId > 0;
	}

	@Override
	public int getItemViewType(int position) {
		if (positionIsHeaderItem(position)){
			return mHeaderItems.get(position).getItemType();
		}

		if (positionIsRemainAreaItem(position)){
			return mRemainAreaItem.getItemType();
		}

		if (positionIsFooterItem(position)){
			return mFooterItems.get(getFooterItemIndex(position)).getItemType();
		}

		return getItemViewType2(position);
	}

	protected int getFooterItemIndex(int position){
		position = position - mHeaderItems.size() - mOriginalAdapter.getItemCount();
		if (hasFullDataArea()){
			position--;
		}
		return position;
	}

	public int getItemViewType2(int position) {
		return mOriginalAdapter.getItemViewType(position);
	}

	public boolean typeIsRemainAreaItem(int type){
		return mRemainAreaItem != null && type == mRemainAreaItem.getItemType();
	}

	@Override
	public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
		//remain
		if (typeIsRemainAreaItem(viewType)){
			return new BaseViewHolder(mRemainAreaItem.getView());
		}
		//header
		SimpleItem headerItem = mHeaderItemTypes.get(viewType);
		if (headerItem != null){
			return new BaseViewHolder(headerItem.getView());
		}
		//footer
		SimpleItem footerItem = mFooterItemTypes.get(viewType);
		if (footerItem != null){
			return new BaseViewHolder(footerItem.getView());
		}
		return onCreateViewHolder2(parent,viewType);
	}

	public RecyclerView.ViewHolder onCreateViewHolder2(ViewGroup parent, int viewType){
		return mOriginalAdapter.onCreateViewHolder(parent,viewType);
	}

	@Override
	public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
		if (positionIsHeaderItem(position)){
			mHeaderItems.get(position).onBindViewHolder((BaseViewHolder) holder,position);
			return;
		}
		if (positionIsRemainAreaItem(position)){
			mRemainAreaItem.onBindViewHolder((BaseViewHolder) holder,position);
			return;
		}
		if (positionIsFooterItem(position)){
			mFooterItems.get(getFooterItemIndex(position)).onBindViewHolder((BaseViewHolder) holder,position);
			return;
		}
		position = position - mHeaderItems.size();
		onBindViewHolder2(holder,position);
	}

	public boolean positionIsRemainAreaItem(int position){
		return hasFullDataArea() && position == mHeaderItems.size() + mOriginalAdapter.getItemCount();
	}

	public boolean positionIsHeaderItem(int position){
		return position < mHeaderItems.size();
	}

	public boolean positionIsFooterItem(int position){
		int count = mHeaderItems.size() + mOriginalAdapter.getItemCount();
		if (hasFullDataArea()) count++;
		return position >= count;
	}

	public void onBindViewHolder2(RecyclerView.ViewHolder holder, int position){
		mOriginalAdapter.onBindViewHolder(holder,position);
	}

	public void convert(CommonViewHolder holder, DataType data){}

	@Override
	public int getItemCount() {
		int count = mOriginalAdapter.getItemCount() + mHeaderItems.size() + mFooterItems.size();
		if (hasFullDataArea()) count++;
		return count;
	}

	public static class BaseViewHolder extends RecyclerView.ViewHolder{

		public BaseViewHolder(View itemView) {
			super(itemView);
		}
	}

	/**
	 * 更新数据时，如果用户当前选择的item位置大于新数据集的总数，则将选中的位置固定到最后
	 */
	private void tryAutoFixPositionToEnd(){
		if (!isTryAutoFixPositionToEnd() || !hasFullDataArea()) return;
		int lastPosition = mRecyclerView.findLastVisibleItemPosition();
		int size = mHeaderItems.size() + mFooterItems.size() + getDataSize() + 1;
		if (lastPosition >= size){
			int index = mHeaderItems.size();
			mRecyclerView.moveToPosition(index);
			if (mDataAreaOffset > 0){
//				mRecyclerView.scrollBy(0,-mDataAreaOffset);
			}
		}
	}

	public List getObjects() {
		if (mCommonAdapter != null){
			return mCommonAdapter.getObjects();
		}
		return null;
	}

	public void updateData(List objects){
		if (mCommonAdapter != null){
			mCommonAdapter.setObjects(objects);
			notifyUpdateData();
		}
	}

	public void notifyUpdateData(){
		mOriginalAdapter.notifyDataSetChanged();
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public void onAttachedToRecyclerView(RecyclerView recyclerView) {
		mOriginalAdapter.onAttachedToRecyclerView(recyclerView);
	}

	@Override
	public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
		mOriginalAdapter.onDetachedFromRecyclerView(recyclerView);
	}

	@Override
	public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
		mOriginalAdapter.onViewAttachedToWindow(holder);
	}

	@Override
	public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
		mOriginalAdapter.onViewDetachedFromWindow(holder);
	}

	@Override
	public void onViewRecycled(RecyclerView.ViewHolder holder) {
		mOriginalAdapter.onViewRecycled(holder);
	}

	@Override
	public boolean onFailedToRecycleView(RecyclerView.ViewHolder holder) {
		return mOriginalAdapter.onFailedToRecycleView(holder);
	}

	@Override
	public void unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {
		mOriginalAdapter.unregisterAdapterDataObserver(observer);
	}

	@Override
	public void registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {
		mOriginalAdapter.registerAdapterDataObserver(observer);
	}

	private class DataObserver extends RecyclerView.AdapterDataObserver {

		@Override
		public void onChanged() {
			if (wantFullDataArea() || hasSetEmptyView()){
				doFullDataArea();
			}
			tryAutoFixPositionToEnd();
			notifyDataSetChanged();
		}

		@Override
		public void onItemRangeInserted(int positionStart, int itemCount) {
			notifyItemRangeInserted(positionStart, itemCount);
		}

		@Override
		public void onItemRangeChanged(int positionStart, int itemCount) {
			notifyItemRangeChanged(positionStart, itemCount);
		}

		@Override
		public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
			notifyItemRangeChanged(positionStart, itemCount, payload);
		}

		@Override
		public void onItemRangeRemoved(int positionStart, int itemCount) {
			notifyItemRangeRemoved(positionStart, itemCount);
		}

		@Override
		public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
			notifyItemMoved(fromPosition, toPosition);
		}
	}
}
